#include "../include/nfs.h"

extern struct nfs_super      nfs_super; 
extern struct custom_options nfs_options;

/**
 * @brief 获取文件名
 * 
 * @param path 
 * @return char* 
 */
char* nfs_get_fname(const char* path) {
    char ch = '/';
    char *q = strrchr(path, ch) + 1;
    return q;
}


/**
 * @brief 计算路径的层级
 * exm: /av/c/d/f
 * -> lvl = 4
 * @param path 
 * @return int 
 */
int nfs_calc_lvl(const char * path) {
    // char* path_cpy = (char *)malloc(strlen(path));
    // strcpy(path_cpy, path);
    char* str = path;
    int   lvl = 0;
    if (strcmp(path, "/") == 0) {
        return lvl;
    }
    while (*str != NULL) {
        if (*str == '/') {
            lvl++;
        }
        str++;
    }
    return lvl;
}


/**
 * @brief 驱动读
 * 
 * @param offset 磁盘块的偏移，字节为单位
 * @param out_content 位于内存的地址
 * @param size 读取多大内容，字节为单位
 * @return int 
 */
int nfs_driver_read(int offset, uint8_t *out_content, int size) {
    int      offset_aligned = NFS_ROUND_DOWN(offset, NFS_IO_SZ());
    int      bias           = offset - offset_aligned;
    int      size_aligned   = NFS_ROUND_UP((size + bias), NFS_IO_SZ());
    uint8_t* temp_content   = (uint8_t*)malloc(size_aligned);
    uint8_t* cur            = temp_content;
    // lseek(NFS_DRIVER(), offset_aligned, SEEK_SET);
    ddriver_seek(NFS_DRIVER(), offset_aligned, SEEK_SET);
    while (size_aligned != 0)
    {
        // read(NFS_DRIVER(), cur, NFS_IO_SZ());
        ddriver_read(NFS_DRIVER(), cur, NFS_IO_SZ());
        cur          += NFS_IO_SZ();
        size_aligned -= NFS_IO_SZ();   
    }
    memcpy(out_content, temp_content + bias, size);
    free(temp_content);
    return NFS_ERROR_NONE;
}


/**
 * @brief 驱动写
 * 
 * @param offset 
 * @param in_content 
 * @param size 
 * @return int 
 */
int nfs_driver_write(int offset, uint8_t *in_content, int size) {
    int      offset_aligned = NFS_ROUND_DOWN(offset, NFS_IO_SZ());
    int      bias           = offset - offset_aligned;
    int      size_aligned   = NFS_ROUND_UP((size + bias), NFS_IO_SZ());
    uint8_t* temp_content   = (uint8_t*)malloc(size_aligned);
    uint8_t* cur            = temp_content;
    nfs_driver_read(offset_aligned, temp_content, size_aligned);
    memcpy(temp_content + bias, in_content, size);
    
    // lseek(NFS_DRIVER(), offset_aligned, SEEK_SET);
    ddriver_seek(NFS_DRIVER(), offset_aligned, SEEK_SET);
    while (size_aligned != 0)
    {
        // write(NFS_DRIVER(), cur, NFS_IO_SZ());
        ddriver_write(NFS_DRIVER(), cur, NFS_IO_SZ());
        cur          += NFS_IO_SZ();
        size_aligned -= NFS_IO_SZ();   
    }

    free(temp_content);
    return NFS_ERROR_NONE;
}


/**
 * @brief 为一个父级目录的inode添加一个子级目录项的dentry（文件/目录/符号）
 * 采用头插法：最新添加的dentry放在inode->dentrys，之前的dentry通过inode->dentrys->brother串起来
 * 
 * @param inode 待插入的目录inode
 * @param dentry 
 * @return int 
 */
int nfs_alloc_dentry(struct nfs_inode* inode, struct nfs_dentry* dentry) {
    // 传入的inode不是目录，返回非法参数错误
    if(!NFS_IS_DIR(inode))
        return NFS_ERROR_INVAL;

    if (inode->dentrys == NULL) {
        inode->dentrys = dentry;
    }
    else {
        dentry->brother = inode->dentrys; // 之前的dentry通过inode->dentrys->brother串起来，形成链表
        inode->dentrys = dentry; // 最新添加的dentry放在inode->dentrys
    }
    inode->dir_cnt++; // 目录项条数加一
    return inode->dir_cnt;
}


// /**
//  * @brief 将dentry从inode的dentrys中取出
//  * 
//  * @param inode 
//  * @param dentry 
//  * @return int 
//  */
// int nfs_drop_dentry(struct nfs_inode * inode, struct nfs_dentry * dentry) {
//     boolean is_find = FALSE;
//     struct nfs_dentry* dentry_cursor;
//     dentry_cursor = inode->dentrys;
    
//     if (dentry_cursor == dentry) {
//         inode->dentrys = dentry->brother;
//         is_find = TRUE;
//     }
//     else {
//         while (dentry_cursor)
//         {
//             if (dentry_cursor->brother == dentry) {
//                 dentry_cursor->brother = dentry->brother;
//                 is_find = TRUE;
//                 break;
//             }
//             dentry_cursor = dentry_cursor->brother;
//         }
//     }
//     if (!is_find) {
//         return -NFS_ERROR_NOTFOUND;
//     }
//     inode->dir_cnt--;
//     return inode->dir_cnt;
// }


/**
 * @brief 为传入的dentry分配一个inode，占用位图。
 * 在1.创建根目录；2.创建目录；3.创建文件时用到
 * 
 * @param dentry 该dentry指向分配的inode
 * @return nfs_inode
 */
struct nfs_inode* nfs_alloc_inode(struct nfs_dentry * dentry) {
    struct nfs_inode* inode;
    int byte_cursor = 0; // 字节指针
    int bit_cursor  = 0; // 位指针
    int ino_cursor  = 0; // 索引位图的下标，第几个索引位
    boolean is_find_free_entry = FALSE;

    // 逐个字节遍历索引位图的每个字节
    for (byte_cursor = 0; byte_cursor < NFS_BLKS_SZ(nfs_super.map_inode_blks); 
         byte_cursor++)
    {
        // 逐位遍历上层取出的字节的每个位
        for (bit_cursor = 0; bit_cursor < UINT8_BITS; bit_cursor++) {
            /* 当前ino_cursor位置空闲 */
            if((nfs_super.map_inode[byte_cursor] & (0x1 << bit_cursor)) == 0) {    
                nfs_super.map_inode[byte_cursor] |= (0x1 << bit_cursor);
                is_find_free_entry = TRUE;           
                break;
            }
            ino_cursor++;
        }
        if (is_find_free_entry) {
            break;
        }
    }

    // 索引位图全部满了
    if (!is_find_free_entry || ino_cursor == nfs_super.max_ino)
        return -NFS_ERROR_NOSPACE;

    // new一个inode结构
    inode = (struct nfs_inode*)malloc(sizeof(struct nfs_inode));
    inode->ino  = ino_cursor; // 添加索引号

    
    /* 更新dentry指向inode */
    dentry->inode = inode;
    dentry->ino   = inode->ino;
    
    /* 同时设置inode指回dentry */
    inode->dentry = dentry;
    
    inode->dir_cnt = 0;
    inode->dentrys = NULL;
    
    /* 刚创建的文件，大小为0，没有使用数据块 */
    // 对于文件，在write的时候，大小才会改变
    // 对于目录，在alloc 和 drop dentry的时候，大小才会改变
    inode->size = 0;
    // inode->data = NULL;
    // if (NFS_IS_REG(inode)) {
    //     for(int i=0; i < NFS_DATA_PER_FILE; i++){
    //         inode->data[i] = (uint8_t *)malloc(NFS_BLK_SZ());
    //     }
    // }

    return inode;
}


/**
 * @brief 将内存inode及其下方结构全部刷回磁盘，该inode的dentry没有被刷？
 * 
 * @param inode 
 * @return int 
 */
int nfs_sync_inode(struct nfs_inode * inode) {
    struct nfs_inode_d  inode_d;
    struct nfs_dentry*  dentry_cursor;
    struct nfs_dentry_d dentry_d;
    int ino             = inode->ino;

    /* 由inode结构体得到待刷的inode_d结构体 */
    inode_d.ino         = ino;
    inode_d.size        = inode->size;
    memcpy(inode_d.target_path, inode->target_path, NFS_MAX_FILE_NAME);
    inode_d.ftype       = inode->dentry->ftype;
    inode_d.dir_cnt     = inode->dir_cnt;
    // 数据块指针
    for(int i =0; i < NFS_DATA_PER_FILE; i++){
        inode_d.data_ptr[i]    = inode->data_ptr[i];
    }

    int cur_dentry; // 放到第几个dentry了


    /* Cycle 1: 写 INODE
       Cycle 2: 写 数据 */
    
    /* 首先刷回了inode对应的inode_d */
    if (nfs_driver_write(NFS_INO_OFS(ino), (uint8_t *)&inode_d, 
                     sizeof(struct nfs_inode_d)) != NFS_ERROR_NONE) {
        NFS_DBG("[%s] io error\n", __func__);
        return -NFS_ERROR_IO;
    }
                                                      
                                                      
    /* 如果该inode是目录 递归刷全部文件 */
    if (NFS_IS_DIR(inode)) {    
        // 空目录 nothing to do 
        // 非空目录
        if(inode->size!=0){
            // 每个数据块可以放多少个条目
            int dentrys_per_blk = NFS_BLK_SZ() / sizeof(struct nfs_dentry_d);


            dentry_cursor = inode->dentrys; // 首当其冲的第一个目录项
            cur_dentry = 0; // 放入的dentry个数   
            while (dentry_cursor != NULL)
            {

                /* 首先刷回了该目录项对应的dentry_d */
                memcpy(dentry_d.fname, dentry_cursor->fname, NFS_MAX_FILE_NAME);
                dentry_d.ftype = dentry_cursor->ftype;
                dentry_d.ino = dentry_cursor->ino;
                if (nfs_driver_write(
                    NFS_DATA_OFS(inode->data_ptr[(cur_dentry+1) / dentrys_per_blk]) + sizeof(struct nfs_dentry_d) * (cur_dentry % dentrys_per_blk), 
                    (uint8_t *)&dentry_d, 
                    sizeof(struct nfs_dentry_d)) != NFS_ERROR_NONE
                    ) {
                    NFS_DBG("[%s] io error\n", __func__);
                    return -NFS_ERROR_IO;                     
                }
            
                /* 然后借助递归刷回了该目录项对应的inode */
                if (dentry_cursor->inode != NULL) {
                    nfs_sync_inode(dentry_cursor->inode);
                }

                /* 接下来刷下一个目录项，从brother处取*/
                dentry_cursor = dentry_cursor->brother;
                cur_dentry += 1;
            }
        }                      
        
    }

    /* 如果该inode是普通文件 写回数据 */
    else if (NFS_IS_REG(inode)) {
        // 空文件 nothing to do
        // 文件非空
        if(inode->size!=0){
            // 根据size获取文件占用了多少个数据块
            int ptr_index = inode->size / NFS_BLK_SZ();
            for(int i=0; i<ptr_index; i++){
                // 根据存储的数据块号，找到偏移，写一块
                if (nfs_driver_write(NFS_DATA_OFS(inode_d.data_ptr[i]), (uint8_t *)inode->data[i], 
                                NFS_BLK_SZ()) != NFS_ERROR_NONE) {
                    NFS_DBG("[%s] io error\n", __func__);
                    return NULL;                    
                }
            }
            // 最后一块可能未对齐
            inode->data[ptr_index] = (uint8_t *)malloc(NFS_BLKS_SZ(NFS_DATA_PER_FILE));
            // 写未对齐的剩下那点
            if (nfs_driver_write(NFS_DATA_OFS(inode_d.data_ptr[ptr_index]), (uint8_t *)inode->data[ptr_index], 
                                (inode->size - (ptr_index * NFS_BLK_SZ())) != NFS_ERROR_NONE)) {
                NFS_DBG("[%s] io error\n", __func__);
                return NULL;                    
            }
            
        }
    }
    return NFS_ERROR_NONE;
}


// /**
//  * @brief 删除内存中的一个inode， 暂时不释放
//  * Case 1: Reg File
//  * 
//  *                  Inode
//  *                /      \
//  *            Dentry -> Dentry (Reg Dentry)
//  *                       |
//  *                      Inode  (Reg File)
//  * 
//  *  1) Step 1. Erase Bitmap     
//  *  2) Step 2. Free Inode                      (Function of nfs_drop_inode)
//  * ------------------------------------------------------------------------
//  *  3) *Setp 3. Free Dentry belonging to Inode (Outsider)
//  * ========================================================================
//  * Case 2: Dir
//  *                  Inode
//  *                /      \
//  *            Dentry -> Dentry (Dir Dentry)
//  *                       |
//  *                      Inode  (Dir)
//  *                    /     \
//  *                Dentry -> Dentry
//  * 
//  *   Recursive
//  * @param inode 
//  * @return int 
//  */
// int nfs_drop_inode(struct nfs_inode * inode) {
//     struct nfs_dentry*  dentry_cursor;
//     struct nfs_dentry*  dentry_to_free;
//     struct nfs_inode*   inode_cursor;

//     int byte_cursor = 0; 
//     int bit_cursor  = 0; 
//     int ino_cursor  = 0;
//     boolean is_find = FALSE;

//     if (inode == nfs_super.root_dentry->inode) {
//         return NFS_ERROR_INVAL;
//     }

//     /* 如果是目录: 
//         1. 遍历每个目录项，从dentrys开始，通过brother
//         2. 递归drop目录项对应的inode
//         3. 从原inode删除该目录项的dentry
//         4. 释放该dentry
//         */
//     if (NFS_IS_DIR(inode)) {
//         dentry_cursor = inode->dentrys;
//         while (dentry_cursor)
//         {   
//             inode_cursor = dentry_cursor->inode;
//             nfs_drop_inode(inode_cursor); /* 递归向下drop inode */
//             nfs_drop_dentry(inode, dentry_cursor); 
//             dentry_to_free = dentry_cursor;
//             dentry_cursor = dentry_cursor->brother;
//             free(dentry_to_free);
//         }
//     }
//     /* 如果是文件：位图修改 + 释放inode */
//     else if (NFS_IS_REG(inode) || NFS_IS_SYM_LINK(inode)) {
//         /* 调整inodemap 将其置为0 */
//         for (byte_cursor = 0; byte_cursor < NFS_BLKS_SZ(nfs_super.map_inode_blks); 
//             byte_cursor++)                            
//         {
//             for (bit_cursor = 0; bit_cursor < UINT8_BITS; bit_cursor++) {
//                 if (ino_cursor == inode->ino) {
//                      nfs_super.map_inode[byte_cursor] &= (uint8_t)(~(0x1 << bit_cursor));
//                      is_find = TRUE;
//                      break;
//                 }
//                 ino_cursor++;
//             }
//             if (is_find == TRUE) {
//                 break;
//             }
//         }
//         /* 释放inode的数据和inode结构 */
//         if (inode->data)
//             free(inode->data);
//         free(inode);
//     }
//     return NFS_ERROR_NONE;
// }


/**
 * @brief 从磁盘中读取第ino个inode_d，并拓展其dentry为传入的dentry，
 *        得到位于内存的inode结构体
 * 
 * @param dentry dentry指向ino，读取该inode
 * @param ino inode唯一编号
 * @return struct nfs_inode* 
 */
struct nfs_inode* nfs_read_inode(struct nfs_dentry * dentry, int ino) {
    struct nfs_inode* inode = (struct nfs_inode*)malloc(sizeof(struct nfs_inode));
    struct nfs_inode_d inode_d;
    struct nfs_dentry* sub_dentry;
    struct nfs_dentry_d dentry_d;
    int    dir_cnt = 0;

    /* 从磁盘中读取ino对应的inode_d结构体 */
    if (nfs_driver_read(NFS_INO_OFS(ino), (uint8_t *)&inode_d, 
                        sizeof(struct nfs_inode_d)) != NFS_ERROR_NONE) {
        NFS_DBG("[%s] io error\n", __func__);
        return NULL;                    
    }

    /* 通过inode_d结构体建立inode结构体 */
    inode->dir_cnt = 0;
    inode->ino = inode_d.ino;
    inode->size = inode_d.size;
    memcpy(inode->target_path, inode_d.target_path, NFS_MAX_FILE_NAME);
    inode->dentry = dentry; // 在内存的inode结构体需要拓展和绑定dentry
    inode->dentrys = NULL;
    // 数据块指针
    for(int i =0; i < NFS_DATA_PER_FILE; i++){
        inode->data_ptr[i]    = inode_d.data_ptr[i];
    }

    /* 注 & Tips*/
    // 若inode_d是个目录，其inode对应的data内容，即ino索引到的数据块的内容是
    // 其全部子目录项的dentry_d结构体组成的dentry_d数组，共有dir_cnt个元素
    // 通过下标遍历，即可遍历全部子目录项的dentry_d结构体

    /* 如果inode_d是个目录
       1.  */
    if (NFS_IS_DIR(inode)) {
        dir_cnt = inode_d.dir_cnt;
        // 遍历子目录项，磁盘读取dentry_d结构体
        for (int i = 0; i < dir_cnt; i++)
        {

            int dentrys_per_blk = NFS_BLK_SZ() / sizeof(struct nfs_dentry_d);  

            if (nfs_driver_read(
                NFS_DATA_OFS(inode->data_ptr[(i+1) / dentrys_per_blk]) + sizeof(struct nfs_dentry_d) * (i % dentrys_per_blk), 
                (uint8_t *)&dentry_d, 
                sizeof(struct nfs_dentry_d)) != NFS_ERROR_NONE
                ) {
                NFS_DBG("[%s] io error\n", __func__);
                return -NFS_ERROR_IO;                     
            }

            // 获得子目录项的基本dentry结构体（只有名字和类型）
            sub_dentry = new_dentry(dentry_d.fname, dentry_d.ftype);
            // 设置子目录项的父指针为当前inode的dentry
            sub_dentry->parent = inode->dentry;
            sub_dentry->ino    = dentry_d.ino; 
            // 添加该子目录项dentry结构到inode下
            nfs_alloc_dentry(inode, sub_dentry);
        }
    }

    /* 如果是文件，根据size从磁盘读取其data到内存 */
    else if (NFS_IS_REG(inode)) {
        // 空文件 nothing to do
        // 文件非空
        if(inode->size!=0){
            // 根据size获取文件占用了多少个数据块
            int ptr_index = inode->size / NFS_BLK_SZ();
            // 获取数据块指针
            for(int i=0; i<ptr_index; i++){
                inode->data[i] = (uint8_t *)malloc(NFS_BLKS_SZ(NFS_DATA_PER_FILE));
                // 根据存储的数据块号，找到偏移，读取一块
                if (nfs_driver_read(NFS_DATA_OFS(inode_d.data_ptr[i]), (uint8_t *)inode->data[i], 
                                NFS_BLK_SZ()) != NFS_ERROR_NONE) {
                    NFS_DBG("[%s] io error\n", __func__);
                    return NULL;                    
                }
            }
            // 最后一块可能未对齐
            inode->data[ptr_index] = (uint8_t *)malloc(NFS_BLKS_SZ(NFS_DATA_PER_FILE));
            // 读取未对齐的剩下那点
            if (nfs_driver_read(NFS_DATA_OFS(inode_d.data_ptr[ptr_index]), (uint8_t *)inode->data[ptr_index], 
                                (inode->size - (ptr_index * NFS_BLK_SZ())) != NFS_ERROR_NONE)) {
                NFS_DBG("[%s] io error\n", __func__);
                return NULL;                    
            }
            
        }

    }
    return inode;
}


/**
 * @brief 用于返回inode对应目录下的第dir个目录项的dentry结构体，通过brother往下查找
 * 
 * @param inode 
 * @param dir [0...]
 * @return struct nfs_dentry* 
 */
struct nfs_dentry* nfs_get_dentry(struct nfs_inode * inode, int dir) {
    struct nfs_dentry* dentry_cursor = inode->dentrys;
    int    cnt = 0;
    while (dentry_cursor)
    {
        if (dir == cnt) {
            return dentry_cursor;
        }
        cnt++;
        dentry_cursor = dentry_cursor->brother;
    }
    return NULL;
}


/**
 * @brief 查找path对应的目录是否存在，并返回上级目录的dentry
 * path: /qwe/ad  total_lvl = 2,
 *      1) find /'s inode       lvl = 1
 *      2) find qwe's dentry 
 *      3) find qwe's inode     lvl = 2
 *      4) find ad's dentry
 *
 * path: /qwe     total_lvl = 1,
 *      1) find /'s inode       lvl = 1
 *      2) find qwe's dentry
 * 
 * @param path 
 * @return path上级目录的dentry
 */
struct nfs_dentry* nfs_lookup(const char * path, boolean* is_find, boolean* is_root) {
    struct nfs_dentry* dentry_cursor = nfs_super.root_dentry;
    struct nfs_dentry* dentry_ret = NULL;
    struct nfs_inode*  inode; 
    int   total_lvl = nfs_calc_lvl(path);
    int   lvl = 0;
    boolean is_hit;
    char* fname = NULL;
    char* path_cpy = (char*)malloc(sizeof(path));
    *is_root = FALSE;
    strcpy(path_cpy, path);

    /* 根目录 */
    if (total_lvl == 0) {                           
        *is_find = TRUE;
        *is_root = TRUE;
        dentry_ret = nfs_super.root_dentry;
    }

    fname = strtok(path_cpy, "/");       
    while (fname)
    {   
        lvl++;
        if (dentry_cursor->inode == NULL) {           /* Cache机制 */
            nfs_read_inode(dentry_cursor, dentry_cursor->ino);
        }

        inode = dentry_cursor->inode;

        if (NFS_IS_REG(inode) && lvl < total_lvl) {
            NFS_DBG("[%s] not a dir\n", __func__);
            dentry_ret = inode->dentry;
            break;
        }
        if (NFS_IS_DIR(inode)) {
            dentry_cursor = inode->dentrys;
            is_hit        = FALSE;

            while (dentry_cursor)
            {
                if (memcmp(dentry_cursor->fname, fname, strlen(fname)) == 0) {
                    is_hit = TRUE;
                    break;
                }
                dentry_cursor = dentry_cursor->brother;
            }
            
            if (!is_hit) {
                *is_find = FALSE;
                NFS_DBG("[%s] not found %s\n", __func__, fname);
                dentry_ret = inode->dentry;
                break;
            }

            if (is_hit && lvl == total_lvl) {
                *is_find = TRUE;
                dentry_ret = dentry_cursor;
                break;
            }
        }
        fname = strtok(NULL, "/"); 
    }

    if (dentry_ret->inode == NULL) {
        dentry_ret->inode = nfs_read_inode(dentry_ret, dentry_ret->ino);
    }
    
    return dentry_ret;
}


/**
 * @brief 挂载nfs, Layout 如下
 * 
 * Layout
 * | Super | Inode Map | Data |
 * 
 * IO_SZ = BLK_SZ
 * 
 * 每个Inode占用一个Blk
 * @param options 
 * @return int 
 */
int nfs_mount(struct custom_options options){
    int                 ret = NFS_ERROR_NONE;
    int                 driver_fd;
    struct nfs_super_d  nfs_super_d; 
    struct nfs_dentry*  root_dentry;
    struct nfs_inode*   root_inode;

    int                 inode_num;
    int                 map_inode_blks;
    int                 map_data_blks;
    
    int                 super_blks;
    boolean             is_init = FALSE;

    nfs_super.is_mounted = FALSE;

    // driver_fd = open(options.device, O_RDWR);
    /* 打开设备驱动 */
    driver_fd = ddriver_open(options.device);

    if (driver_fd < 0) {
        return driver_fd;
    }

    nfs_super.driver_fd = driver_fd;
    ddriver_ioctl(NFS_DRIVER(), IOC_REQ_DEVICE_SIZE,  &nfs_super.sz_disk);
    ddriver_ioctl(NFS_DRIVER(), IOC_REQ_DEVICE_IO_SZ, &nfs_super.sz_io);
    
    // new空白的根目录
    root_dentry = new_dentry("/", NFS_DIR);

    /* 通过设备驱动 从磁盘读取 原生的super_d */
    if (nfs_driver_read(NFS_SUPER_OFS, (uint8_t *)(&nfs_super_d), 
                        sizeof(struct nfs_super_d)) != NFS_ERROR_NONE) {
        return -NFS_ERROR_IO;
    }   

    /* 幻数无: 说明磁盘没有初始化 or 出错了，需要重新设置超级块！*/                            
    if (nfs_super_d.magic_num != NFS_MAGIC) { 
        // 设置逻辑块的大小
        nfs_super.sz_block = 1024; // 字节为单位
        

        // 估算各部分大小
        super_blks = NFS_ROUND_UP(sizeof(struct nfs_super_d), NFS_BLK_SZ()) / NFS_BLK_SZ() ; // 手动计算超级块占用的块数

        inode_num  =  NFS_DISK_SZ() / ((NFS_DATA_PER_FILE + NFS_INODE_PER_FILE) * NFS_BLK_SZ()); // 文件/inode的个数
        // 每个文件最大可分配16个块（8个数据块），每个文件还需要1个块用于索引块
        // 一个文件对应一个inode
        // 文件/inode的个数 = 磁盘总大小 / (文件占块数(16+1) * 块大小)

        // map_inode_blks = NFS_ROUND_UP(NFS_ROUND_UP(inode_num, UINT32_BITS), NFS_IO_SZ())
        //                  / NFS_IO_SZ();

        // 索引位图的块数
        // 一个文件1个索引块
        map_inode_blks = NFS_ROUND_UP((NFS_ROUND_UP(inode_num, UINT32_BITS) / UINT8_BITS), NFS_BLK_SZ())
                         / NFS_BLK_SZ();

        // 数据位图的块数
        // 一个文件8个数据块
        map_data_blks = NFS_ROUND_UP((NFS_ROUND_UP((inode_num * NFS_DATA_PER_FILE),
                                                 UINT32_BITS) / UINT8_BITS), NFS_BLK_SZ()) / NFS_BLK_SZ();

        
        /* 布局layout: 布局原始的、静态位于的超级块 */

        // 布局: | Super(1) | Inode Map(1) | DATA Map(1) | Inode(452) | DATA(*) |
        // 其中每个文件的DATA固定为DATA(16)

        nfs_super.max_ino = (inode_num - super_blks - map_inode_blks - map_data_blks); // 文件数
        nfs_super_d.map_inode_offset = NFS_SUPER_OFS + NFS_BLKS_SZ(super_blks);
        nfs_super_d.map_data_offset = nfs_super_d.map_inode_offset +  NFS_BLKS_SZ(map_inode_blks);
        nfs_super_d.inode_offset = nfs_super_d.map_data_offset + NFS_BLKS_SZ(map_data_blks);
        nfs_super_d.data_offset = nfs_super_d.inode_offset + NFS_BLKS_SZ((inode_num - super_blks - map_inode_blks - map_data_blks));
        nfs_super_d.map_inode_blks  = map_inode_blks;
        nfs_super_d.map_data_blks  = map_data_blks;
        nfs_super_d.sz_usage    = 0;
        nfs_super_d.sz_block = nfs_super.sz_block;
        NFS_DBG("inode map blocks: %d\n", map_inode_blks);
        is_init = TRUE;
    }

    /* 建立 in-memory 结构：创建位于内存的，动态的、拓展的超级块 */
    nfs_super.sz_usage   = nfs_super_d.sz_usage;  
    nfs_super.sz_block   = nfs_super_d.sz_block;     
    
    nfs_super.map_inode = (uint8_t *)malloc(NFS_BLKS_SZ(nfs_super_d.map_inode_blks));
    nfs_super.map_inode_blks = nfs_super_d.map_inode_blks;
    nfs_super.map_inode_offset = nfs_super_d.map_inode_offset;

    nfs_super.map_data = (uint8_t *)malloc(NFS_BLKS_SZ(nfs_super_d.map_data_blks));
    nfs_super.map_data_blks = nfs_super_d.map_data_blks;
    nfs_super.map_data_offset = nfs_super_d.map_data_offset;

    nfs_super.inode_offset = nfs_super_d.inode_offset;

    nfs_super.data_offset = nfs_super_d.data_offset;

    // 从磁盘读取索引位图的具体数据到内存的超级块结构中
    if (nfs_driver_read(nfs_super_d.map_inode_offset, (uint8_t *)(nfs_super.map_inode), 
                        NFS_BLKS_SZ(nfs_super_d.map_inode_blks)) != NFS_ERROR_NONE) {
        return -NFS_ERROR_IO;
    }

    // 从磁盘读取数据位图的具体数据到内存的超级块结构中
    if (nfs_driver_read(nfs_super_d.map_data_offset, (uint8_t *)(nfs_super.map_data), 
                        NFS_BLKS_SZ(nfs_super_d.map_data_blks)) != NFS_ERROR_NONE) {
        return -NFS_ERROR_IO;
    }

    /* 分配根节点 */
    // 第一次初始化中，需要为根节点创建inode，并刷回磁盘
    if (is_init) {                                    
        root_inode = nfs_alloc_inode(root_dentry); // 创建inode
        nfs_sync_inode(root_inode); // 刷回磁盘
    }
    
    // 正常情况下，直接从磁盘读取第0个inode即可
    root_inode            = nfs_read_inode(root_dentry, NFS_ROOT_INO);
    root_dentry->inode    = root_inode;
    nfs_super.root_dentry = root_dentry;
    nfs_super.is_mounted  = TRUE;

    nfs_dump_map();
    return ret;
}


/**
 * @brief 
 * 
 * @return int 
 */
int nfs_umount() {
    struct nfs_super_d  nfs_super_d; 

    if (!nfs_super.is_mounted) {
        return NFS_ERROR_NONE;
    }

    /* 从根节点向下刷写节点 */
    nfs_sync_inode(nfs_super.root_dentry->inode);     

    /* 由在内存中的super创建待写回的super_d*/                                  
    nfs_super_d.magic_num           = NFS_MAGIC;
    nfs_super_d.sz_usage            = nfs_super.sz_usage;
    nfs_super_d.sz_block            = nfs_super.sz_block;
    nfs_super_d.map_inode_blks      = nfs_super.map_inode_blks;
    nfs_super_d.map_inode_offset    = nfs_super.map_inode_offset;
    nfs_super_d.map_data_blks      = nfs_super.map_data_blks;
    nfs_super_d.map_data_offset    = nfs_super.map_data_offset;
    nfs_super_d.data_offset         = nfs_super.data_offset;
    nfs_super_d.inode_offset         = nfs_super.inode_offset;

    /* 写回超级块 */
    if (nfs_driver_write(NFS_SUPER_OFS, (uint8_t *)&nfs_super_d, 
                     sizeof(struct nfs_super_d)) != NFS_ERROR_NONE) {
        return -NFS_ERROR_IO;
    }

    /* 写回索引位图 */
    if (nfs_driver_write(nfs_super_d.map_inode_offset, (uint8_t *)(nfs_super.map_inode), 
                         NFS_BLKS_SZ(nfs_super_d.map_inode_blks)) != NFS_ERROR_NONE) {
        return -NFS_ERROR_IO;
    }

    /* 写回数据位图 */
    if (nfs_driver_write(nfs_super_d.map_data_offset, (uint8_t *)(nfs_super.map_data), 
                         NFS_BLKS_SZ(nfs_super_d.map_data_blks)) != NFS_ERROR_NONE) {
        return -NFS_ERROR_IO;
    }

    free(nfs_super.map_inode);
    free(nfs_super.map_data);
    ddriver_close(NFS_DRIVER());

    return NFS_ERROR_NONE;
}




/**
 * @brief 申请一个可用的数据块
 * 
 * @param 
 * @return int 可用的一个数据块的块号
 */
int nfs_alloc_data_block() {
    int byte_cursor = 0; // 字节指针
    int bit_cursor  = 0; // 位指针
    int data_cursor  = 0; // 索引位图的下标，第几个索引位
    boolean is_find_free_entry = FALSE;

    // 最大文件数 * 每个文件占用数据块数 8个
    int max_data_blks =  nfs_super.max_ino * NFS_DATA_PER_FILE; // 最大数据块的块号

    // 逐个字节遍历数据位图的每个字节
    for (byte_cursor = 0; byte_cursor < NFS_BLKS_SZ(nfs_super.map_data_blks); 
         byte_cursor++)
    {
        // 逐位遍历上层取出的字节的每个位
        for (bit_cursor = 0; bit_cursor < UINT8_BITS; bit_cursor++) {
            /* 当前ino_cursor位置空闲 */
            if((nfs_super.map_data[byte_cursor] & (0x1 << bit_cursor)) == 0) {    
                nfs_super.map_data[byte_cursor] |= (0x1 << bit_cursor);
                is_find_free_entry = TRUE;           
                break;
            }
            data_cursor++;
        }
        if (is_find_free_entry) {
            break;
        }
    }

    // 数据位图全部满了 或者 数据块不够用了
    if (!is_find_free_entry || data_cursor == max_data_blks)
        return -NFS_ERROR_NOSPACE;

    return data_cursor;
}



/**
 * @brief 维护一个inode的数据块索引信息和inode的大小
 * 
 * @param 新增加的内容大小
 * @return int 添加成功与否
 */
int nfs_update_inode_size_and_ptr(struct nfs_inode*  inode, int new_size){
    /* 目录文件的大小改变 数据位图修改*/

    if(NFS_IS_DIR(inode)){
        // 该inode是个目录，new_size为一个条目大小，用碎片式存放

        if(new_size > NFS_BLK_SZ()) // 这个条目太大了。。
            return NFS_ERROR_INVAL;

        if(inode->size==0) // 空目录
            // 申请一个数据块，并添加到data_ptr中
            inode->data_ptr[0] = nfs_alloc_data_block();
        else { // 非空目录 
            int ptr_index = inode->size / (NFS_BLK_SZ()); // 当前使用到第几个数据块
            int new_ptr_index = (inode->size + new_size) / 
                                (NFS_BLK_SZ()); // 装下new_size使用到第几个数据块
            if(ptr_index < new_ptr_index){
                if(new_ptr_index == NFS_DATA_PER_FILE) // 大小超了
                    return NFS_ERROR_NOSPACE ;

                // 剩下的碎片不要了，新开一个数据块
                inode->data_ptr[new_ptr_index] = nfs_alloc_data_block();
                inode->size = NFS_ROUND_UP(inode->size, (NFS_BLK_SZ())); 
            }
        }

        inode->size = inode->size + new_size;
    }
    else if(NFS_IS_REG(inode)){
        // 该inode是个普通文件，则连续式存放
        // 暂时不涉及文件读写，文件大小为0
        return NFS_ERROR_INVAL;
    }


    return NFS_ERROR_NONE;
}